package com.cloudlinkin.util.redis;

import com.cloudlinkin.util.PropertiesKit;
import com.cloudlinkin.util.error.RecordingExceptionControl;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisSentinelPool;

import java.util.HashSet;
import java.util.Set;

public class _JedisPoolQueue {
	private static JedisPool jedisPool = null;

	private static JedisSentinelPool jedisSentinePool = null;

	private static Logger log = Logger.getLogger(_JedisPoolQueue.class);

	private static JedisPoolConfig config = new JedisPoolConfig();

	private static Set<String> redisMasterAddr = new HashSet<String>();

	private static boolean isOpenSentinePool = false;

	private static int errorCount = 0;

	/**
	 * 初始化Redis连接池
	 */
	static {
		try {
			PropertiesKit prop = new PropertiesKit("redis.properties");
			config.setMaxTotal(prop.getInteger("redisMaxActive"));
			config.setMaxIdle(prop.getInteger("redisMaxIdle"));
			config.setMaxWaitMillis(prop.getInteger("redisMaxWait"));
			config.setTestOnBorrow(prop.getBoolean("redisTestOnBorrow"));
			config.setTestOnReturn(prop.getBoolean("redisTestOnReturn"));
			// 是否开启哨兵模式
			isOpenSentinePool = prop.getBoolean("redisIsOpenSentinePool");
			if (isOpenSentinePool) {// 如果使用哨兵模式
				// 初始化 redisMasterAddr集合
				String[] masters = prop.get("redisMasterAddrQueue").trim().split("\\|");
				for (int i = 0; i < masters.length; i++) {
					redisMasterAddr.add(masters[i]);
				}
				if (StringUtils.isBlank(prop.get("redisPwd")))
					jedisSentinePool = new JedisSentinelPool(prop.get("queueMaster"), redisMasterAddr, config,
							prop.getInteger("redisTimeout"));
				else
					jedisSentinePool = new JedisSentinelPool(prop.get("queueMaster"), redisMasterAddr, config,
							prop.getInteger("redisTimeout"), prop.get("redisPwd"));

			} else if (!isOpenSentinePool) {
				if (StringUtils.isBlank(prop.get("redisPwd")))
					jedisPool = new JedisPool(config, prop.get("redisIp"), prop.getInteger("redisPort"),
							prop.getInteger("redisTimeout"));
				else
					jedisPool = new JedisPool(config, prop.get("redisIp"), prop.getInteger("redisPort"),
							prop.getInteger("redisTimeout"), prop.get("redisPwd"));

			}

		} catch (Exception e) {
			log.error("初始化 redis 连接池失败",e);
		}
	}

	/**
	 * 获取Jedis实例
	 * 
	 * @return
	 */
	@SuppressWarnings("static-access")
	public static synchronized Jedis getJedis() {
		Jedis jedis = null;
		do {
			if (errorCount >= 3) {
				errorCount = 0;
				return null;
			}
			try {
				// 判断是否开启哨兵
				if (isOpenSentinePool) {
					if (null != jedisSentinePool)
						jedis = jedisSentinePool.getResource();

				} else {
					if (null != jedisPool)
						jedis = jedisPool.getResource();
				}
				errorCount = 0;
				RecordingExceptionControl.controlClear();
			} catch (Exception e) {
				e.printStackTrace();
				log.error("连接redis服务失败:" + (errorCount + 1));
				RecordingExceptionControl.controlRecordingException("RedisError","Mail-JedisPool-getJedis:Redis连接失败");
				try {
					Thread.currentThread().sleep(1000);
					errorCount++;
				} catch (InterruptedException e1) {
				}
			}
		} while (errorCount != 0);
		return jedis;
	}

	/**
	 * 释放jedis资源
	 * 
	 * @param jedis
	 */
	public static void returnResource(Jedis jedis) {
		if (jedis != null) {
			jedis.close();
		}
	}

}
